//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// cl_fit_mv - Ajusta curva de luz de binarias a dados observados utilizando
//			   Cadeias de Markov. 
//
// Qua 25 Ago 2010 16:54:40 BRT:
// - Inicio do programa. Quero tentar deixar esse programa o mais organizado 
//	possivel. Vou passar a tarefa de ler os arquivos de entrada e tudo mais
//  para classes externas e tentar fazer uma maneira inteligente de escolher
//	quais parametros serao ajustados.
// 
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

#include "cl_fit_mc_v0_1.h" // Cabecalhos

#include "cl_fit_error_handle.hpp"

//Fazer libs para linkar qdo pronto!
#include "cl_fit_fit_funcs.cpp"
#include "cl_fit_input_funcs.cpp"
#include "cl_fit_data_funcs.cpp"


int main(int argc, char **argv)
{
		
	// Lendo arquivos de entrada
	//PReader inpar(argv[1]);
	//DataReader indat(argv[2]);
	
	cout << argc << endl;
	for (int i = 0; i < argc; ++i) {
		cout << argv[i] << "  ";
	}
	cout << endl;
	
	SimAnSolve solve(argv[1],argv[2]);

	// Mostro infos de arquivos de entrada
	solve.show_par(cout);
	solve.info();
	solve.show_FitPar(cout);
	solve.T0(100);
	solve.dT(0.9);
	solve.NPerturb(10000);
	solve.NSuccess(2000);
	
	// Tirando f_fac1 da lista de parametros a ajustar
	// inc, M2, f2, f_fac2, f1
	int i_FitPar[] = {1,1,2,2,3}; // linha do vetor de parametros a ser ajustado
	int j_FitPar[] = {0,2,0,5,0}; //	coluna do vetor de parametros a ser ajustado
	int nFitPar = 5;
	solve.FitPar(nFitPar,i_FitPar,j_FitPar);
	
	for (int i = 0; i < 100; ++i) {
		int rr = ++solve;
		cout << rr << " " << solve.T0() << " " << solve.dT() << endl;
		if (rr < 0) break;
	}
	
	exit(0);
	
}


/*
{
	// Testar argumentos de entrada...
	
	if(argc < 4){
		cout << "Modo de utilizacao do programa:\n"
		<< "\tpar_finder arq_data arq_par arq_out\n\n" 
		<< "Onde arq_data o arquivo com os dados (curva de luz) para" 
		<< " minimizar o qui2 com\n"
		<< "curva modelo de estrelas secundarias preenchendo (ou nao) o lobo"
		<< "de Roche.\n"
		<< "arq_par os parametros para o modelo incluindo os parametros" 
		<< "atmosfericos e os valores iniciais para serem utilizados no simplex\n."
		<< "arq_out o arquivo para serem escritos os resultados.\n"
		// << "Alternativamente pode-se incluir um arquivo 'arq_log' para o programa\n"
		// << "colocar as saidas (stdout eh padrao). Util no caso de se rodar em"
		// << "background.\n"
		<< "Formato de arq_data:\n"
		<< "Fase Fluxo Flux_err\n"
		<< "Formato de arq_par:\n"
		<< "1a. linha de dados (sem contar linha de comentario), valores" 
		<< " iniciais do simplex:\n"
		<< "  i   - inclinacao (graus).\n"
		<< "  q   - Razao de massa.\n"
		<< "  p_s - Posicao do spot em relacao a L1 (em graus).\n" 
		<< "  I_s - Razao de brilho de um spot gaussiano.\n"
		<< "  fd  - fluxo do disco (constante somada a curva de luz).\n"
		<< "  f2  - fluxo da secundaria em fase 0.\n"
		<< "2a. linha de dados (fator multiplicando o passo, default = 1.0):\n"
		<< "   i q ps {Is fd f2}*Ncl f_fac\n"
		<< "3a. linha de dados:\n"
		<< "  grav_coef - coeficiente do obscurecimento gravitacional.\n"
		<< "  limb_law  - lei de obscurecimento de borda.\n"
		<< "  Tpole     - Temperatura do polo da estrela.\n"
		<< "  f_fac     - Fator multiplicativo ao potencial do lobo de\n"
		<< "  f2m - fluxo MAXIMO da secundaria em fase 0.\n"
		<< "         Roche, que define a superficie da estrela secundaria.\n"
		<< "3a. linha de dados:\n"
		<< "  (coeficientes de obscurecimento de borda)\n"
		<< "Tiago Ribeiro - LinuxC++ - 2007\n";
		exit(1);
	}
	
    // Ler curvas de luz...
	
	DataFileReader inlis(argv[1]); // lista de inputs
	int clcount=0;
	DataKeeper dk_par;
	
	while(!++inlis){
		DataFileReader indata(inlis.readColumn<string>(1));
		//inlis.seteol();
		dk_par.cur_luz.push_back( vector<Data>() );
		while(!++indata){
			Data read_tmp;
			indata >> read_tmp.fase >> read_tmp.flux >> read_tmp.ferr;
			dk_par.cur_luz.at(clcount).push_back(read_tmp);
			//indata.seteol();
			//++indata;
		}
		indata.close();
		//++inlis;
		++clcount;
	}
	
	inlis.close();
	
	// Input File Definition - IFD:  
	//     Number of fixed Parameters lines      -  IFD_NP
	//     Number of columns Parameters          - *IFD_P (array[IFD_NP])
	//     Spot Line(onde com. def. de spot - 1) -  IFD_SL
	//     Number of Spot Parameters             -  IFD_SP
	//     posicao da lei de obs. de Borda       -  IFD_B
	
	const int IFD_NP = 3;
	const int IFD_P[IFD_NP] = {3+(dk_par.cur_luz.size()*3),4+(dk_par.cur_luz.size()*3), 5}; //{i,q,ps} + Ncl*{Is,fd,f2}
	//const int IFD_SL = 0; SPOT DEFINIDO NA LINHA 1
	//const int IFD_SP = 5;
	const int IFD_B = 1;
	const int F2M_POS[2] = {1,4}; //posicao do f2m no vetor de parametros
	const int N_TRIES = 2;             // * how many points do we try before stepping 
	const int ITERS_FIXED_T = 1000;      // * how many iterations for each T? 
	const double STEP_SIZE = 0.01;           // * max step size in random walk 
	const double K = 1.0;                   // * Boltzmann constant 
	const double T_INITIAL = 10.;         // * initial temperature 
	const double MU_T = 1.05; //1.003;              // * damping factor for temperature 
	const double T_MIN = 0.01;
	
	
	DataFileReader fin(argv[2]);
	//++fin;
	
	vector<vector<double> > in_par(IFD_NP+1);
	double f2m;
	//Lendo linha 1 e 2
	
	for(int i = 0; i < IFD_NP; i++){
		++fin;
		int Flag_f2m = 0;
		if(fin.numberOfColumns() == IFD_P[i]){
			double data_in;
			//      if(i == 0) Flag_f2m = 1;
			for(int j = 0; j < IFD_P[i]; j++){
				fin >> data_in;
				if(i == 0 && j == 0) data_in *= M_PI/180; //transforma i em radianos
				in_par[i].push_back(data_in);
			}
		}
		else { 
			ostringstream erro;
			erro << "Numero de parametros errado\n\tArquivo: " 
			<< argv[2] << "\n\tLinha  : " << fin.lineNumber();
			aborta(erro.str());
		}
		//if(Flag_f2m == 1){
		//  fin >> f2m; 
		//}
		//++fin;
		
		// *  if(fin.eof()) {
		 ostringstream erro;
		 erro << "Numero de parametros errado\n\tArquivo: " 
		 << argv[2] << "\n\tLinha  : " << fin.lineNumber();
		 aborta(erro.str());
		 }
		 * /
	}
	
	//Lendo linha 3
	++fin;
	if(fin.numberOfColumns()==definicoes_obscurecimento(int(in_par[2][IFD_B]))){
		double data_in;
		for(int i = 0; i < definicoes_obscurecimento(int(in_par[2][IFD_B])); i++){
			fin >> data_in;
			in_par[3].push_back(data_in);
		}
	}
	else {
		ostringstream erro;
		erro << "Numero de parametros errado\n\tArquivo: " 
		<< argv[2] << "\n\tLinha  : " << fin.lineNumber()
		<< "\n\tEsperado : " << definicoes_obscurecimento(int(in_par[2][IFD_B]))
		<< "\n\tLido     : " << fin.numberOfColumns();
		aborta(erro.str());
	}
	
	fin.close();
	
	show_par(cout, in_par);
	
	// Estrutura que guarda os parametros...
	
	ofstream output(argv[3]);
	
	dk_par.par = in_par;
	dk_par.f2max = in_par[F2M_POS[0]][F2M_POS[1]];
	dk_par.saida = &output;
	
	//Fim das besteiras, hora de minimizar qui2...
	// Utilizando gsl...
	
	const gsl_rng_type * T;
	gsl_rng * gen_rand;
	
	gsl_rng_env_setup();
	T = gsl_rng_default;
	gen_rand = gsl_rng_alloc(T);
	gsl_siman_params_t params = {N_TRIES, ITERS_FIXED_T, STEP_SIZE,
		K, T_INITIAL, MU_T, T_MIN};
	
	// *  
	 gsl_siman_solve(gen_rand, &dk_par, qui2, do_step, how_far, print_cfg,
	 copy, create_cfg, destroy,
	 0, params);
	 * /
	
	siman_solve(gen_rand, &dk_par, qui2, do_step, how_far, print_cfg, 
				params,copy,create_cfg,destroy);
	
	output.close();
}

*/
